<template>
  <NvLayout :nvs-data="nvsData" :is-root-layout="true" @define-event="handleEvent($event)" style="margin: 5px;" v-if="nvsData">
  </NvLayout>
</template>
<script>
import { onMounted, ref } from 'vue'
import NvsData from '../../js/NvsData'
import nvsDataUtils from '../../js/NvsDataUtils'
import NvLayout from '../../components/compound/NvLayout'
import ConstDef from '../../js/ConstDef'
import nvService from '../../api/NvService'
import cacheManage from '../../cache/CacheManage'
import { ElMessage } from 'element-plus'
import partyEntryExt from './ext/entryext/PartyEntryExt'
import layoutEntryExt from "./ext/entryext/LayoutEntryExt";

export default {
  name: 'NvEntry',
  components: {
    NvLayout
  },
  props: {
    config: Object,
    default: null
  },
  setup(props, context) {
    const nvsData = ref(null);
    const entryExts = ref(
      {
        partyEntryExt, layoutEntryExt
      }
    )

    function getQueryApiMethod() {
      if (entryExtHasApiName('getNv')) {
        return entryExtApiName('getNv');
      } else {
        return {
          func: nvService.getNv,
          obj: nvService
        }
      }
    }

    function getQueryByCodeApiMethod() {
      if (entryExtHasApiName('getNvByCode')) {
        return entryExtApiName('getNvByCode');
      } else {
        return {
          func: nvService.getNvByCode,
          obj: nvService
        }
      }
    }

    onMounted(async () => {
      if (props.config.action === 'show') {
        nvsData.value = props.config.nvsData;
        return;
      }
      if (props.config.parentNvCode && props.config.parentNvId <= 0) {
        ElMessage({
          type: 'error',
          message: '录入配置parentNvCode，但是parentNvId为为空!',
          showClose: true
        })
        return;
      }
      const ndCode = props.config.ndCode
      const layoutCode = props.config.layoutCode
      if (props.config.action === 'init') {
        const nvsDataMsg = await nvsDataUtils.initNvAndNdAndLayout(ndCode, layoutCode)
        if (!nvsDataMsg.success) {
          return;
        }
        nvsDataMsg.nv.parentId = props.config.parentNvId;
        nvsData.value = new NvsData([nvsDataMsg.nv], nvsDataMsg.nd, nvsDataMsg.layout);
      } else if (props.config.action === 'query') {
        const nvId = props.config.nvId
        const nvCode = props.config.nvCode;
        let nvsDataMsg;
        if (nvId > 0) {
          nvsDataMsg = await nvsDataUtils.getNvAndNdAndLayout(nvId, ndCode, layoutCode, getQueryApiMethod())
        } else if (nvCode) {
          nvsDataMsg = await nvsDataUtils.getNvAndNdAndLayoutByCode(nvCode, props.config.codeFdName, ndCode, layoutCode, getQueryByCodeApiMethod())
        } else return;
        if (!nvsDataMsg.success) {
          return;
        }
        nvsData.value = new NvsData([nvsDataMsg.nv], nvsDataMsg.nd, nvsDataMsg.layout);
      } else if (props.config.action === 'copy') {
        const nvId = props.config.nvId;
        const nvsDataMsg = await nvsDataUtils.copyNvAndNdAndLayout(nvId, ndCode, layoutCode);
        if (!nvsDataMsg.success) {
          return;
        }
        nvsDataMsg.nv.parentId = props.config.parentNvId;
        nvsData.value = new NvsData([nvsDataMsg.nv], nvsDataMsg.nd, nvsDataMsg.layout);
      } else if (props.config.action === 'create') {
        const nv = props.config.nv;
        const ndAndLayoutMsg = await nvsDataUtils.getNdAndLayout(ndCode, layoutCode);
        if (!ndAndLayoutMsg.success) {
          return;
        }
        nvsData.value = new NvsData([nv], ndAndLayoutMsg.nd, ndAndLayoutMsg.layout);
      }
    })

    function getNvsData() {
      return nvsData.value;
    }

    function getNvs() {
      return nvsData.value.nvs;
    }

    function entryExtInterceptEvent(functionCode) {
      if (props.config.extCode && entryExts.value[props.config.extCode]) {
        if (entryExts.value[props.config.extCode].interceptEvent(functionCode)) {
          return true;
        }
      }
      return false;
    }
    function entryExtSupportEvent(functionCode) {
      if (props.config.extCode && entryExts.value[props.config.extCode]) {
        if (entryExts.value[props.config.extCode].supportEvent(functionCode)) {
          return true;
        }
      }
      return false;
    }
    function entryExtApiName(apiName) {
      if (props.config.extCode && entryExts.value[props.config.extCode]) {
        return entryExts.value[props.config.extCode].getAPIMethod(apiName);
      } else return null;
    }

    function entryExtHasApiName(apiName) {
      if (props.config.extCode && entryExts.value[props.config.extCode]) {
        return (entryExts.value[props.config.extCode].hasAPIMethod(apiName));
      } else {
        return false;
      }
    }

    function getFunctionConfig() {
      return {
        config: props.config,
        moduleCode: ConstDef.MODULE_CODE_ENTRY
      }
    }

    return {
      nvsData,
      getNvsData,
      getNvs,
      entryExts,
      entryExtSupportEvent,
      entryExtInterceptEvent,
      entryExtApiName,
      entryExtHasApiName,
      getFunctionConfig
    };
  },
  methods: {
    async saveNv(event) {
      const commonInfo = cacheManage.getDefaultCommonInfo();
      const nvs = this.nvsData.getNvs();
      const nd = this.nvsData.nd;
      nvsDataUtils.setNvsChangeOperationFlag(nvs, nd);
      let nvMsg;
      if (this.entryExtHasApiName('saveNvs')) {
        const saveNvsInfo = this.entryExtApiName('saveNvs');
        nvMsg = await saveNvsInfo.func.call(saveNvsInfo.obj, commonInfo, nvs);
      } else {
        nvMsg = await nvService.saveNvs(commonInfo, nvs);
      }
      if (!nvMsg.success) return;
      ElMessage({
        message: '保存成功!',
        type: 'success',
        plain: true
      })
      this.nvsData.nvs = nvMsg.value;
    },
    async commitNv(event) {
      const commonInfo = cacheManage.getDefaultCommonInfo();
      const expression = event.fvData.fdLayout.expression ? JSON.parse(event.fvData.fdLayout.expression) : {};
      commonInfo.transactionType = expression.transaction ? expression.transaction : ConstDef.TRANSACTION_TYPE_COMMIT;
      const nvs = this.nvsData.getNvs();
      const nd = this.nvsData.nd;
      nvsDataUtils.setNvsChangeOperationFlag(nvs, nd);
      let nvMsg;
      if (this.entryExtHasApiName('commitNvs')) {
        const commitNvsInfo = this.entryExtApiName('commitNvs');
        nvMsg = await commitNvsInfo.func.call(commitNvsInfo.obj, commonInfo, nvs);
      } else {
        nvMsg = await nvService.commitNvs(commonInfo, nvs);
      }
      if (!nvMsg.success) return;
      ElMessage({
        message: '提交成功!',
        type: 'success',
        plain: true
      })
      this.nvsData.nvs = nvMsg.value;
    },
    async deleteById(event) {
      const commonInfo = cacheManage.getDefaultCommonInfo();
      const fvData = event.fvData;
      const ndCode = fvData.nd.ndCode;
      const nv = fvData.getNv;
      const nvId = nv.id;
      if (nvId > 0) {
        const deleteMsg = await nvService.deleteNvById(commonInfo, ndCode, nvId);
        if (deleteMsg.success) {
          ElMessage({
            message: '删除成功!',
            type: 'success',
            plain: true
          })
        }
      }
      const nvs = this.fvData.nvs;
      const index = nvs.findIndex(function (item) {
        return item === nv;
      });
      nvs.splice(index, 1);
    },
    async handleEvent(event) {
      const fvData = event.fvData;
      const functionCode = fvData.fdLayout.functionCode;
      if (this.entryExtInterceptEvent(functionCode)) {
        const entryExt = this.entryExts[this.config.extCode];
        entryExt.handleEvent(this, event);
      } else if (functionCode === ConstDef.FUNCTION_CODE_SAVE) {
        this.saveNv(event);
      } else if (functionCode === ConstDef.FUNCTION_CODE_COMMIT) {
        this.commitNv(event);
      } else if (functionCode === ConstDef.FUNCTION_CODE_DELETE) {
        this.deleteById(event);
      } else if (this.entryExtSupportEvent(functionCode)) {
        const entryExt = this.entryExts[this.config.extCode];
        entryExt.handleEvent(this, event);
      } else {
        this.$emit("define-event", event)
      }
    }
  }
}
</script>

<style scoped>

</style>
